﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Text;

namespace TfL
{
    public interface IStationTrainTimesFeed : ITrackerNetFeedPoller<TrainTimesForStation>, ISubject<TrainTimesForStation>
    {
        IStationTrainTimesFeed Station(string station);
        string Name { get; }
    }

    public class StationTrainTimesFeed : IDisposable, IStationTrainTimesFeed
    {

        public StationTrainTimesFeed(string url, string ns,string station)
        {
            _station = station;
            foreach(string line in LineCodes.Names)
            {
                _lineStationTrainTimes.Add(new TrainTimesFeed(url,ns,line));
            }
        }

        public IStationTrainTimesFeed Station(string station)
        {
            _station = station;
            return this;
        }

        public string Name
        {
            get { return _station; }
            
        }

        #region IObserver<StationTrainTimes> Members

        public void OnCompleted()
        {
            _subject.OnCompleted();
        }

        public void OnError(Exception error)
        {
            _subject.OnError(error);
        }

        public void OnNext(TrainTimesForStation value)
        {
            System.Diagnostics.Debug.WriteLine(value);
            _subject.OnNext(value);
        }

        #endregion

        #region IObservable<TrainTimesForStation> Members

        public IDisposable Subscribe(IObserver<TrainTimesForStation> observer)
        {
            return _subject.Subscribe(observer);
        }

        #endregion

        private readonly Subject<TrainTimesForStation> _subject = new Subject<TrainTimesForStation>();

        #region ITrackerNetFeedPoller<StationTrainTimes> Members

        public ISubject<TrainTimesForStation> Poll()
        {
            _subscribers.ForEach(d=>d.Dispose());
            _subscribers.Clear();
            foreach(var observable in _lineStationTrainTimes)
            {
                var subscriber = from t in observable.Poll()
                                 where t.Name.Contains(Name)
                                 select t;
                _subscribers.Add(subscriber.Subscribe(OnNext));
            }
            return this;
        }

        public ISubject<TrainTimesForStation> Poll(System.Threading.CancellationToken token, int period)
        {
            foreach (var subscriber in _lineStationTrainTimes.Select(observable => (from t in observable.Poll(token,period)
                                                                                    where t.Name == Name
                                                                                    select t)))
            {
                _subscribers.Add(subscriber.Subscribe(OnNext));
            }
            return this;
        }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            foreach (var subscriber in _subscribers)
            {
                subscriber.Dispose();
            }
        }

        #endregion

        private string _station;

        private readonly List<IDisposable> _subscribers = new List<IDisposable>(); 

        private readonly List<TrainTimesFeed> _lineStationTrainTimes = new List<TrainTimesFeed>();

        
    }
}
